package com.houseliker.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.houseliker.R;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class IGifViewForSplash extends View {

    private static final int DEFAULT_MOVIE_DURATION = 1000;

    private Movie mMovie;

    private long mMovieStart;

    private int mCurrentAnimationTime = 0;

    private float scaleX;
    private float scaleY;

    private int mMeasuredMovieWidth;

    private int mMeasuredMovieHeight;

    private boolean mVisible = true;

    private volatile boolean mPaused = false;

    public IGifViewForSplash(Context context) {
        this(context, null);
    }

    public IGifViewForSplash(Context context, AttributeSet attrs) {
        this(context, attrs, R.styleable.GifTheme_gifViewStyle);
    }

    @SuppressLint("NewApi")
    public IGifViewForSplash(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setViewAttributes(context, attrs, defStyle);
    }

    private int mMovieResourceId;

    @SuppressLint("NewApi")
    private void setViewAttributes(Context context, AttributeSet attrs, int defStyle) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }
        final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.GifView,
                defStyle, R.style.Widget_GifView);
        mMovieResourceId = array.getResourceId(R.styleable.GifView_gif, -1);
        mPaused = array.getBoolean(R.styleable.GifView_paused, false);
        array.recycle();
        if (mMovieResourceId != -1) {
            mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));
        }
    }

    /**
     * 设置GifView显示属性
     *
     * @param movie 对应背景的GIF资源
     */
    public void setDrawable(Movie movie) {
        setMovie(movie);
    }

    /**
     * 设置GifView显示属性
     *
     * @param bitmap 对应背景的图片
     */
    public void setDrawable(Bitmap bitmap) {
        setImage(bitmap);
    }

    /**
     * 设置GifView显示属性
     */
    public void setDrawable() {
        try {
            byte[] buffer = null;
            InputStream is = getResources().openRawResource(R.raw.splash);
//                File file = new File(filePath);
//                FileInputStream is = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = is.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            is.close();
            bos.close();
            buffer = bos.toByteArray();
            mMovie = Movie.decodeByteArray(buffer, 0, buffer.length);
            requestLayout();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            System.gc();
        }
    }

    /**
     * 设置GifView显示属性
     *
     * @param isGif 是否是GIF
     */
    public void setDrawableFromNet(String Url, boolean isGif) {
        new DownLoadDrawable(Url, isGif).start();
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case -1:
                    Log.e("error:", "gifViewDownloadError!");
                    break;
                case 1:
                    Bundle bundle = msg.getData();
                    setDrawable();
                    break;
            }
        }
    };

    private class DownLoadDrawable extends Thread {
        private String url;
        private boolean isGif;

        public DownLoadDrawable(String url, boolean isGif) {
            this.url = url;
            this.isGif = isGif;
        }

        @Override
        public void run() {
            super.run();
            try {
                String adPath = ".jpg";
                File file = new File(adPath);
                if (file.exists()) {
                } else {
                    URL imageUrl = new URL(url);
                    // URL imageUrl = new URL(mFileUrl);
                    HttpURLConnection con = (HttpURLConnection) imageUrl.openConnection();
                    con.setConnectTimeout(10 * 1000);
                    con.setReadTimeout(10 * 1000);
                    con.setDoInput(true);
                    con.connect();
                    if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        if (saveFile(con.getInputStream(), adPath)) {
                        } else {
                            handler.sendEmptyMessage(-1);
                        }
                    }
                }
                Message msg = new Message();
                msg.what = 1;
                Bundle bundle = new Bundle();
                bundle.putString("filePath", adPath);
                bundle.putBoolean("isGif", isGif);
                msg.setData(bundle);
                handler.sendMessage(msg);
            } catch (Exception e) {
                e.printStackTrace();
                handler.sendEmptyMessage(-1);
            }
        }

        public boolean saveFile(InputStream is, String mFilePath) {
            try {
                FileOutputStream fos = new FileOutputStream(new File(mFilePath));
                byte[] buff = new byte[1024];
                int length = 0;
                while ((length = is.read(buff)) != -1) {
                    fos.write(buff, 0, length);
                }
                is.close();
                fos.close();
                return true;
            } catch (IOException e) {
                File file = new File(mFilePath);
                if (file.exists()) {
                    if (file.isFile()) {
                        file.delete();
                    }
                }
                return false;
            }
        }
    }

    private void setImage(Bitmap bitmap) {
        this.setBackgroundDrawable(new BitmapDrawable(bitmap));
    }

    private void setMovie(Movie movie) {
        this.mMovie = movie;
        requestLayout();
    }

    public Movie getMovie() {
        return mMovie;
    }

    public void setMovieTime(int time) {
        mCurrentAnimationTime = time;
        invalidate();
    }

    public void setPaused(boolean paused) {
        this.mPaused = paused;
        if (!paused) {
            mMovieStart = android.os.SystemClock.uptimeMillis() - mCurrentAnimationTime;
        }
        invalidate();
    }

    public boolean isPaused() {
        return this.mPaused;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mMovie != null) {
            int movieWidth = mMovie.width();
            int movieHeight = mMovie.height();
            int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec);
            if (measureModeWidth != MeasureSpec.UNSPECIFIED) {
                int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);
                if (movieWidth != 0) {
                    scaleX = (float) maximumWidth / (float) movieWidth;

                } else {
                    scaleX = 1.0f;
                }
                mMeasuredMovieWidth = maximumWidth;
            } else {
                mMeasuredMovieWidth = movieWidth;
            }
            int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec);
            if (measureModeHeight != MeasureSpec.UNSPECIFIED) {
                int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);
                if (movieHeight != 0) {
                    scaleY = (float) maximumHeight / (float) movieHeight;
                } else {
                    scaleY = 1.0f;
                }
                mMeasuredMovieHeight = maximumHeight;
            } else {
                mMeasuredMovieHeight = movieHeight;
            }

            setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight);
        } else {
            // 没有movie，使用父控件希望的大小
            int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);
            int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);
            setMeasuredDimension(
                    (getSuggestedMinimumWidth() > maximumWidth ? getSuggestedMinimumWidth()
                            : maximumWidth),
                    (getSuggestedMinimumHeight() > maximumHeight ? getSuggestedMinimumHeight()
                            : maximumHeight));
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mVisible = getVisibility() == View.VISIBLE;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mMovie != null) {
            if (!mPaused) {
                updateAnimationTime();
                drawMovieFrame(canvas);
                invalidateView();
            } else {
                drawMovieFrame(canvas);
            }
        }
    }

    @SuppressLint("NewApi")
    private void invalidateView() {
        if (mVisible) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                postInvalidateOnAnimation();
            } else {
                invalidate();
            }
        }
    }

    private void updateAnimationTime() {
        long now = android.os.SystemClock.uptimeMillis();
        if (mMovieStart == 0) {
            mMovieStart = now;
        }
        int dur = mMovie.duration();
        if (dur == 0) {
            dur = DEFAULT_MOVIE_DURATION;
        }
        mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
    }

    private void drawMovieFrame(Canvas canvas) {
        mMovie.setTime(mCurrentAnimationTime);
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.scale(scaleX, scaleY);
        mMovie.draw(canvas, 0, 0);
        canvas.restore();
    }

    @SuppressLint("NewApi")
    @Override
    public void onScreenStateChanged(int screenState) {
        super.onScreenStateChanged(screenState);
        mVisible = screenState == SCREEN_STATE_ON;
        invalidateView();
    }

    @SuppressLint("NewApi")
    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        mVisible = visibility == View.VISIBLE;
        invalidateView();
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        mVisible = visibility == View.VISIBLE;
        invalidateView();
    }

}
